crawler imitating browser

crawler imitating browser

模拟浏览器

htmlunit

htmlUnit是java实现的无界面浏览器程序。网站地址:http://htmlunit.sourceforge.net/

在写HtmlUnit代码的时候,仿佛感觉到的就是在操作浏览器而非写代码,得到页面(getPage)– 寻找到文本框(getElementByID || getElementByName || getElementByXPath 等等)– 输入文字(type,setValue,setText等等)– 其他一些类似操作 – 找到提交按钮 – 提交 – 得到新的Page,这样就非常像一个人在后台帮你操作浏览器一样,而你要做的就是告诉他如何操作以及需要填入哪些值。

其原理比较简单,就是模拟浏览器点击输入操作,利用

1
2
WebClient webclient = new WebClient();//htmlunit 是一款开源的 java 页面分析工具,启动 htmlunit 之后,底层会启动一个无界面浏览器,用户可以指定浏览器类型:firefox、ie 等,如果不指定,默认采用 INTERNET_EXPLORER_7:
webclient.getPage(url);

可以获得页面对象HtmlForm,然后可以使用其API进行操作,表单的填充,表单的提交,模仿点击链接,由于内置了Rhinojs引擎,因此可以执行Javascript。其底层还是使用的httpClient来实现的。

很重要的一点是,HtmlUnit 提供对执行 javascript 的支持:
page.executeJavaScript(javascript)
执行 js 之后,返回一个 ScriptResult 对象,通过该对象可以拿到执行 js 之后的页面等信息。默认情况下,内部浏览器在执行 js 之后,将做页面跳转,跳转到执行 js 之后生成的新页面,如果执行 js 失败,将不执行页面跳转。最后可以取得page.executeJavaScript(javascript).getNewPage(),获取执行后的页面。

要加快速度,则可以禁用css,图片,flash等等。

设置等待

1.显式等待

明确的等待是指在代码进行下一步操作之前等待某一个条件的发生。selenium webdriver提供了一些方法帮助我们等待正好需要等待的时间。利用WebDriverWait类和ExpectedCondition接口就能实现这一点。

1
2
3
4
5
6
7
8
WebDriverWait wait = new WebDriverWait(driver, 10);
driver.findElement(By.id("b")).click();
WebElement wl = wait.until(new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver d) {
return d.findElement(By.cssSelector(".red_box"));
}
});
隐式等待

隐性的等待其实就相当于设置全局的等待,在定位元素时,对所有元素设置超时时间。

1
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

参见selenium webdriver学习(十一)————如何等待页面元素加载完成

maven依赖
1
2
3
4
5
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.18</version>
</dependency>
POST方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
URL url = new URL("http://www2.baidu.com");
WebRequestSettings reqSet = new WebRequestSettings(url,SubmitMethod.POST);
List reqParam = new ArrayList();
reqParam.add(new NameValuePair("entered_login", username));
reqParam.add(new NameValuePair("entered_password", password));
reqParam.add(new NameValuePair("entered_imagecode", verifycode));
reqSet.setRequestParameters(reqParam);
HtmlPage mypage = (HtmlPage)client.getPage(reqSet);

htmlUnit介绍

问题
  1. 它与selenium是什么关系,跟phantomJS是同一层级的么?

    我的理解是跟phantomJS、chrome、firefox等等是同一个层级,只不过是无界面的浏览器。selenium是提供了对其的驱动支持,直接内置了驱动。

  2. 有些地方是导入com.gargoylesoftware.htmlunit;但有些地方是用org.openqa.selenium.htmlunit.HtmlUnitDriver。

    我的理解是都可以,com.gargoylesoftware.htmlunit是http://htmlunit.sourceforge.net/项目中的写法,是最初的项目。写法就是

    1
    2
    WebClient webclient = new WebClient();
    webclient.getPage(url);

    但是后来htmlUnit又被集成到了selenium中,提供了一个htmlUnitDriver,所以也可以用selenium中的来开发。写法是

    1
    2
    3
    WebDriver driver=new HtmlUnitDriver();
    //WebDriver driver=new PhantomJSDriver(); //如果是phantomJS,
    driver.get(url);
优点

网页的模拟化

网络响应的自动处理化

并行和串行控制

  1. js错误处理监听机制
  2. 链接响应监听

缓存机制

各个driver的优缺点比较

driver类型 优点 缺点
真实浏览器 真实模拟用户行为 效率、稳定性低
htmlunit 速度快 其引擎不是主流的浏览器支持的,对js支持的不够好
phantomJS 速度中等,模拟行为接近真实 不能模拟不同/特定浏览器的行为

参考博客

htmlunit优缺点

HttpClient和HtmlUnit的比较总结以及使用技巧(一)

htmlunit使用技巧

搜索、查询具体怎么写参见HtmlUnit实现ajax网络爬虫htmlunit官网简易教程(翻译)

用htmlUnit进行爬虫,参见HtmlUnit 网络爬虫 菜鸟的学习笔记(一)

HtmlUnit2.14使用样例—获取动态网页

HtmlUnit、httpclient、jsoup爬取网页信息并解析

selenium综合教程

selenium webdriver学习

webdriver中文社区

python 调用selenium备忘

黄亿华使用Selenium来抓取动态加载的页面